import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter_chip/utils/log_util.dart';
import 'package:flutter_chip/utils/sp_utils.dart';

import 'Api.dart';
import 'Comm.dart';

class Http {
  static String token;
  static Dio _dio;

  static Dio createInstance() {
    if (_dio == null) {
      var headers = Map<String, String>();
      headers['platform'] = Platform.isAndroid ? "Android" : "IOS";
      headers['version'] = Comm.versionName;
      headers['Content-Type'] = 'application/json';
      _dio = new Dio();
      _dio.options.baseUrl = Api.BASE_URL;
      _dio.options.receiveTimeout = 10000;
      _dio.options.connectTimeout = 10000;
      _dio.options.headers = headers;
    }
    return _dio;
  }

  static Future get(String url,
      {Function successCallBack,
      Map<String, String> params,
      Map<String, String> header,
      String path,
      Function errorCallBack}) async {
    await _request(url, successCallBack,
        method: "GET",
        params: params,
        header: header,
        path: path,
        errorCallBack: errorCallBack);
  }

  //post请求
  static Future post(String url,
      {Function successCallBack,
      Map<String, Object> params,
      Map<String, String> header,
      String path,
      Function errorCallBack}) async {
    await _request(url, successCallBack,
        method: "POST",
        params: params,
        header: header,
        path: path,
        errorCallBack: errorCallBack);
  }

  ///上传文件
  static Future upload(String url, List<File> files,
      {Function successCallBack, Function errorCallBack}) async {
    String errorMsg = "";
    int statusCode;
    Response response;
    if (null == files || files.isEmpty) {
      _handError(errorCallBack, errorMsg: "文件不能为空");
      return;
    }
    try {
      _dio = createInstance();
      String token = await SpUtils.get(SpUtils.SP_TOKEN, "");
      if (null != token && token.isNotEmpty) {
        _dio.options.headers["Token"] = token;
      }

      LogUtil.v("===============================================", tag: "Http");
      LogUtil.v("请求地址：${_dio.options.baseUrl}$url", tag: "Http");
      LogUtil.v("请求头：${_dio.options.headers}", tag: "Http");
      FormData formData = FormData();
      for (var i = 0; i < files.length; i++) {
        File file = files[i];
        String path = file.path;
        var name = path.substring(path.lastIndexOf("/") + 1, path.length);
        formData.files.add(
            MapEntry("file", MultipartFile.fromFileSync(path, filename: name)));
      }
      response = await _dio.post(url, data: formData);
      statusCode = response.statusCode;
      if (200 != statusCode) {
        errorMsg = "$statusCode  ${response.statusMessage}";
        _handError(errorCallBack, errorMsg: errorMsg);
        return;
      }
      LogUtil.v("请求响应：${response.data}", tag: "Http");
      LogUtil.v("===============================================", tag: "Http");
      if (successCallBack != null) {
        int code = response.data['code'];
        if (code == 0) {
          successCallBack(json.encode(response.data['data']));
        } else {
          _handError(errorCallBack, errorMsg: response.data['msg']);
        }
      }
    } on DioError catch (exception) {
      _handError(errorCallBack, error: exception);
    } catch (e) {
      LogUtil.e("未知异常:${e.toString()}", tag: "Http");
      _handError(errorCallBack, errorMsg: "请求出错");
    }
  }

  static Future _request(String url, Function callback,
      {String method,
      Map<String, Object> params,
      Map<String, String> header,
      String path,
      Function errorCallBack}) async {
    String errorMsg = "";
    int statusCode;
    Response response;
    try {
      _dio = createInstance();
      String token = await SpUtils.get(SpUtils.SP_TOKEN, "");
      if (null != token && token.isNotEmpty) {
        _dio.options.headers["Token"] = token;
      }
      if (null != header && header.isNotEmpty) {
        _dio.options.headers.addAll(header);
      }

      LogUtil.v("===============================================", tag: "Http");
      LogUtil.v("请求地址：${_dio.options.baseUrl}$url", tag: "Http");
      LogUtil.v("请求头：${_dio.options.headers}", tag: "Http");
      LogUtil.v("请求参数：$method  $params", tag: "Http");

      if (method == "GET") {
        //组合GET请求的参数
        if (params != null && params.isNotEmpty) {
          StringBuffer sb = new StringBuffer("?");
          params.forEach((key, value) {
            sb.write("$key" + "=" + "$value" + "&");
          });
          String paramStr = sb.toString();
          paramStr = paramStr.substring(0, paramStr.length - 1);
          url += paramStr;
        }
        response = await _dio.get(url);
      } else if (method == "PUT") {
        if (params != null && params.isNotEmpty) {
          response = await _dio.put(url, queryParameters: params);
        } else {
          response = await _dio.put(url);
        }
      } else {
        if (params != null && params.isNotEmpty) {
          response = await _dio.post(url, queryParameters: params);
        } else {
          response = await _dio.post(url);
        }
      }

      statusCode = response.statusCode;
      if (200 != statusCode) {
        errorMsg = "$statusCode  ${response.statusMessage}";
        _handError(errorCallBack, errorMsg: errorMsg);
        return;
      }
      LogUtil.v("请求响应：${response.data}", tag: "Http");
      LogUtil.v("===============================================", tag: "Http");
      if (callback != null) {
        int code = response.data['code'];
        if (code == 0) {
          callback(json.encode(response.data['data']));
        } else {
          _handError(errorCallBack, errorMsg: response.data['msg']);
        }
      }
    } on DioError catch (exception) {
      _handError(errorCallBack, error: exception);
    } catch (e) {
      LogUtil.e("未知异常:${e.toString()}", tag: "Http");
      _handError(errorCallBack, errorMsg: "请求出错");
    }
  }

  static void _handError(Function errorCallback,
      {DioError error, String errorMsg}) {
    String message = null != error ? error.message : errorMsg;
    if (null != error) {
      switch (error.type) {
        case DioErrorType.CONNECT_TIMEOUT:
          message = "网络连接超时，请检查网络设置";
          break;
        case DioErrorType.RECEIVE_TIMEOUT:
          message = "服务器异常，请稍后重试！";
          break;
        case DioErrorType.SEND_TIMEOUT:
          message = "网络连接超时，请检查网络设置";
          break;
        case DioErrorType.RESPONSE:
          message = "服务器异常，请稍后重试！";
          break;
        case DioErrorType.CANCEL:
          message = "请求已被取消，请重新请求";
          break;
        case DioErrorType.DEFAULT:
          message = "网络异常，请稍后重试！";
          break;
      }
    }
    if (null != errorCallback) {
      errorCallback(message);
    }
    LogUtil.v("请求出错：${error.toString()}", tag: "Http");
    LogUtil.v("===============================================", tag: "Http");
  }
}
